package com.calvin.study.multithread.threadutils;

import java.util.Date;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.util.RandomUtil;

//CyclicBrrier：N 个线程相互等待，直到有足够数量的线程都到达屏障点之后，之前等待的线程就可以继续执行了。
//好比LOL打团，肯定不止打一次团，可能打1，2，3…次
//CyclicBrrier 就像老司机开车一样，如果车上还有空余的座位，那么所有人都得等着，直到座位被坐满之后，老司机才会发车。

//该示例CyclicBarrier作用，是让一组线程相互等待，当达到一个共同点时，所有之前等待的线程再继续执行，且 CyclicBarrier 功能可重复使用
public class CyclicBarrierDemo01 {

	public static void main(String[] args) {

		// 创建 CyclicBarrier
		final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> System.out.println("人满了，发车：" + new Date()));

		// 线程调用的任务
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				// 生成随机数 1-3
				int randomNumber = RandomUtil.randomInt(1, 3);
				// 进入任务
				System.out.println(String.format("我是：%s 还有：%d 秒就到车站了，现在时间：%s", Thread.currentThread().getName(),
						randomNumber, new Date()));
				try {
					// 模拟执行
					TimeUnit.SECONDS.sleep(randomNumber);
					// 调用 CyclicBarrier
					cyclicBarrier.await();
					// 任务执行
					System.out.println(String.format("线程：%s 上车，时间：%s", Thread.currentThread().getName(), new Date()));
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (BrokenBarrierException e) {
					e.printStackTrace();
				}
			}
		};

		// 创建线程池
		ExecutorService threadPool = Executors.newFixedThreadPool(10);
		// 执行任务 1
		threadPool.submit(runnable);
		// 执行任务 2
		threadPool.submit(runnable);
		// 执行任务 3
		threadPool.submit(runnable);
		// 执行任务 4
		threadPool.submit(runnable);

		// 等待所有任务执行完终止线程池
		threadPool.shutdown();
	}

}
